(function ($) {
    $.fn.ChatPanel = function (conn) {
        function sanitizeUrl(url) {
            return "";
        }

        function sanitizeId(id) {
            return "";
        }

        var self = this;
        var socket = conn;

        this.onPublicMessage = function (evt) {
            var el = $('<li class="message">').appendTo(self);

            // get SELF_UID from document DOM
            var uid = $(document).get(0).SELF_UID;

            if (evt.sender.id == uid) {     // myself
                el.addClass('self');
            }

            var txt = html_sanitize(evt.message, sanitizeUrl, sanitizeId);
            el.append('<span class="nick">' + evt.sender.username + ': </span>' +
				'<span class="msg-text">' + txt + '</span>');
            scrollList();
        }

        this.onAdminMessage = function (evt) {
            var el = $('<li class="admin">').appendTo(self);
            el.append(evt.user.username + '. ' + evt.message);
            scrollList();
        }

        this.onConnection = function (evt) {
            var el = $('<li class="message self">').appendTo(self);
            el.append('<span class="connect">Connected to Nekom.</span>');
            scrollList();

            //-----------------------------------------------------------------
            // NOT REQUIRE SEND LOGIN REQUEST / AUTO LOGIN WITH PHP SESSION
            //-----------------------------------------------------------------
            //socket.send({ command: 'loginRequest' });
            //-----------------------------------------------------------------
        }

        this.onConnectionLost = function (evt) {
            // if kick by server
            if (evt.code == 1) {
                //conn.disconnect();
            }

            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="notice">You have been disconnected from the server. ' +
                evt.reason + '</span>');
            scrollList();
        }

        this.onLogin = function (evt) {
            var uname = evt.user.username;
            var el = $('<li class="message self">').appendTo(self);
            el.append('<span class="login">Has logged in to server with name ' +
                uname + '</span>');
            scrollList();

            //-----------------------------------------------------------------
            // save self UID/UNAME
            //-----------------------------------------------------------------
            $.extend($(document).get(0), { SELF_UID: evt.user.id,
                SELF_UNAME: evt.user.username
            });
            socket.send({ command: 'joinRoomRequest', id: 'lobby' });
        }

        this.onLoginError = function (evt) {
            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="notice">You have been disconnected from the server.</span>');
            scrollList();
        }

        this.onLogout = function (evt) {
            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="logout">Disconnected.</span>');
            scrollList();
        }

        this.onRoomJoin = function (evt) {
            var el = $('<li class="message self">').appendTo(self);
            el.append('<span class="join">Has joined in to room <span class="nick">' +
                evt.room.id + '</span></span>');
            scrollList();
        }

        this.onRoomJoinError = function (evt) {
            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="notice">You have been disconnected from the server.</span>');
            scrollList();
        }

        this.onUserExitRoom = function (evt) {
            // get SELF_UID from document DOM
            var uid = $(document).get(0).SELF_UID;

            if (evt.user.id == uid) {     // if this is myself in another tab/browser
                return;
            }

            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="notice"><spane class="nice">' +
                evt.user.username + '</span> has left the room.</span>');
            scrollList();
        }

        this.onUserEnterRoom = function (evt) {
            // get SELF_UID from document DOM
            var uid = $(document).get(0).SELF_UID;

            if (evt.user.id == uid) {     // if this is myself in another tab/browser
                return;
            }

            var el = $('<li class="message">').appendTo(self);
            el.append('<span class="notice"><spane class="joined">' +
                evt.user.username + ' has joined the room.</span>');
            scrollList();
        }

        function scrollList() {
            self.scrollTop(self[0].scrollHeight - self[0].clientHeight);
        }

        // event notifies the result of a connection attempt.
        // event { 'type': connection, 'result': true/false[, evt] }
        socket.bind('connection', this.onConnection);

        // event notifies the disconnection from the Server.
        // event { 'type': connectionLost, 'reason': manual/kick/ban/unknown[, evt] }
        socket.bind('connectionLost', this.onConnectionLost);

        // event is dispatched in response to a login request.
        // event { 'type': login, 'message': message, 'user': { 'id': id, 'username': name }[, evt] }
        socket.bind('login', this.onLogin);

        // event is dispatched in response to a failed login request.
        // event { 'type': loginError, 'message': message, 'code': code[, evt] }
        socket.bind('loginError', this.onLoginError);

        // event is dispatched in response to a logout request.
        // event { 'type': logout }
        socket.bind('logout', this.onLogout);

        // event is fired whenever a User enters one of the Rooms where the current User is joined.
        // event { 'type': userEnterRoom, 'room': { 'id': id, 'username': name, 'users': users }, 
        // 'user': { 'id': id, 'name': name }[, evt] }
        socket.bind('userEnterRoom', this.onUserEnterRoom);

        // event is fired whenever a User leaves one of the Rooms where the current User is joined.
        // event { 'type': userExitRoom, 'room': { 'id': id, 'name': name, 'users': users }, 
        // 'user': { 'id': id, 'username': name }[, evt] }
        socket.bind('userExitRoom', this.onUserExitRoom);

        // event is dispatched in response to a login request.
        // event { 'type': roomJoin, 'room': { 'id': id, 'name': name, 'users': users }, 
        // 'user': { 'id': id, 'username': name }[, evt] }
        socket.bind('roomJoin', this.onRoomJoin);

        // event is dispatched in response to a failed login request.
        // event { 'type': roomJoinError, message: message, code: code[, evt] }
        socket.bind('roomJoinError', this.onRoomJoinError);

        // event is fired when a User sends a public message.
        // event { 'type': publicMessage, room { 'id': id, 'name': name }, 
        // 'message': message, 'sender': { 'id': id, 'username': name }[, evt] }
        socket.bind('publicMessage', this.onPublicMessage);

        // event is fired when a User receives a Admin message.
        // event { 'type': adminMessage, message: message, sender: { 'id': id, 'username': name } }
        socket.bind('adminMessage', this.onAdminMessage);

        // event is fired when a User receives a Moderator message.
        // event { 'type': moderatorMessage, message: message, sender: { 'id': id, 'username': name } }
        socket.bind('moderatorMessage', this.onModeratorMessage);

        return this;
    }
})(jQuery);

